package com.mattmckay.server;



import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;



import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClient;
import com.amazonaws.services.sqs.model.CreateQueueRequest;
import com.amazonaws.services.sqs.model.DeleteMessageRequest;
import com.amazonaws.services.sqs.model.Message;
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
import com.amazonaws.services.sqs.model.SendMessageRequest;

/**
* <p>Title: Server</p>
* <p>Description: Our server where we are able to 
* save, load, and modify our pdf files. </p>
* @author Matt, Tom, Andrew, Kong
* @email matt.mckay@my.uwrf.edu,tom.florin@my.uwrf.edu,
* andrew.kathan@my.uwrf.edu,kong.xiong-1@my.uwrf.edu
* @date December 1st,2011*/

public class Server implements Runnable{

	private String pdfbucket = "bucket.pdf";
	private String pngbucket = "bucket.png";
	private String pngsqs = "https://queue.amazonaws.com/277957951592/sqspng";
	private String pdfsqs = "https://queue.amazonaws.com/277957951592/sqspdf";

	private AmazonS3 s3;
	private AmazonSQS sqs;
	Server() throws IOException {
		s3 = new AmazonS3Client(new PropertiesCredentials(
				Server.class.getResourceAsStream("AwsCredentials.properties")));
		sqs = new AmazonSQSClient(new PropertiesCredentials(
				Server.class.getResourceAsStream("AwsCredentials.properties")));
	}
	/**
	 * Returns an instance of the server
	 * @return new Server
	 * @throws IOException
	 */
	public static Server getInstance() throws IOException{
		return new Server();
	}
	/**
	 * Creates a message on information regarding
	 * the server
	 */
	public void run() {
		RunCheck();
		try {
		while (true) {
			List<Message> messages = CheckforPDFSQSMessage();
			for (Message message : messages) {
				
					putObject(ProcessPDF.ConvertPDFtoPNG(getObject(message)), message.getBody());
					SubmitMessageAndUpdateQueue(message.getBody(),message.getReceiptHandle());
					System.out.println("User notified via queue");
					Thread.sleep(250);
			}
		}

		} catch (IOException e) {
			System.out.println("IMAGEIO ERROR SERVER.RUN: "+ e.getMessage());
		}catch(InterruptedException ie){
			System.out.println("Error: Server.Run: "+ie.getMessage());
		}catch (Exception ex) {
			System.out.println("General EXCEPTION: Server.RUN: "+ ex.getMessage());
		}
	}
	/**
	 * Finds pdf files, and if they are not found
	 * they are created.
	 */
	private void RunCheck() {
		try {
			if (!FindBucket(pdfbucket)) {
				s3.createBucket(pdfbucket);
				System.out.println("pdf bucket created");
			}
			if (!FindBucket(pngbucket)) {
				s3.createBucket(pngbucket);
				System.out.println("png bucket created");
			}
			if (!FindQueue(pngsqs)) {
				sqs.createQueue(new CreateQueueRequest("pngsqs"));
				System.out.println("png Simple Queue Created");
			}
			if (!FindQueue(pdfsqs)) {
				sqs.createQueue(new CreateQueueRequest("pdfsqs"));
				System.out.println("pdf Simple Queue Created");
			}

		} catch (AmazonS3Exception ase) {
			System.out.println("ERROR in Server.RunCheck: "+ase.getMessage());
		}
	}
	/**
	 * Puts the image into the PNG folder
	 * @param image
	 * @param message
	 */
	public void putObject(byte[] image,String message){
		try{
		InputStream stream = new ByteArrayInputStream(image);
		ObjectMetadata meta = new ObjectMetadata();
		meta.setContentLength(image.length);
		meta.setContentType("application/png");
		s3.putObject(pngbucket,message, stream, meta);
		System.out.println("File has been putted");
		stream.close();
		}catch(Exception ex)
		{
			System.out.println("Error: Server.putObject: "+ex.getMessage());
		}
	}
	
	/**
	 * Retrieves the file from the server
	 * @param message
	 * @return
	 */
	protected InputStream getObject(Message message){
		S3Object object = s3.getObject(pdfbucket, message.getBody());
		System.out.println("File has been getted");
		return object.getObjectContent();
		
	}
	/**
	 * Checks to see if the Bucket is found. Returns true if one is found
	 * or false if it is not found.
	 * @param bucketname
	 * @return true
	 */
	protected boolean FindBucket(String bucketname) {
		for (Object bucket : s3.listBuckets()) {
			if (bucketname.equals( ((Bucket) bucket).getName())) {
				System.out.println("Bucket found!: "+ ((Bucket)bucket).getName());
				return true;
			}
		}
		return false;
	}
	/**
	 * Creates a message about the status of the PNG, and deletes the message from the 
	 * original quene that was used to request the PNG.
	 * @param message
	 * @param messagehandle
	 */
	protected void SubmitMessageAndUpdateQueue(String message, String messagehandle)
	{
		sqs.sendMessage(new SendMessageRequest(pngsqs, message));
		sqs.deleteMessage(new DeleteMessageRequest(pdfsqs,messagehandle));
	}
	/**
	 * FindQuene finds the message Quene for the S3 server.
	 * @param queuename
	 * @return true
	 */
	protected boolean FindQueue(String queuename) {
		for (Object queue : sqs.listQueues().getQueueUrls()) {
			if ( ((String)queue).equals(queuename)) {
				System.out.println("Queue found!: "+queue );
				return true;
			}
		}
		return false;
	}
	/**
	 * Checks the S3 server for message requests
	 * @return messages
	 */
	protected List<Message> CheckforPDFSQSMessage() {
		ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(pdfsqs);
		List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages();
		return messages;
	}
}
